#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "libusb.h"
#include "types.h"
#include "input_stuff.h"
#include "remote.h"
#include "control.h"
#include "ir.h"
#include "crc7.h"


#define DEFAULT_USB_DEVICE_VID		0x16C0
#define DEFAULT_USB_DEVICE_UID		0x05de


static unsigned int USB_VID = 0x16C0;
static int USB_VID_READY = 0;

static unsigned int USB_UID = 0x05de;
static int USB_UID_READY = 0;

static char PORT[32];
static int PORT_READY = 0;

static int PIN;
static int PIN_READY = 0;

static int SETIO;
static int SETIO_READY = 0;

static int GETIO;
static int GETIO_READY = 0;

static int ECHO;
static int ECHO_READY = 0;

static char CFGPIN[32];
static int CFGPIN_READY = 0;

static int RESET;
static int RESET_READY = 0;

static int WRFREG;
static int WRFREG_READY = 0;

static int RRFREG;
static int RRFREG_READY = 0;

static int ADR;
static int ADR_READY = 0;

static int VAL;
static int VAL_READY = 0;

static int BIT;
static int BIT_READY = 0;

static int CFR;
static int CFR_READY = 0;

static int SFR;
static int SFR_READY = 0;

static int REMOTE;
static int REMOTE_READY = 0;

static int WIO8;
static int WIO8_READY = 0;

static int RIO8;
static int RIO8_READY = 0;

static int CIO8;
static int CIO8_READY = 0;

static int SIO8;
static int SIO8_READY = 0;

static int WMEM8;
static int WMEM8_READY = 0;

static int RMEM8;
static int RMEM8_READY = 0;

static int CMEM8;
static int CMEM8_READY = 0;

static int SMEM8;
static int SMEM8_READY = 0;

static int ISOUT;
static int ISOUT_READY = 0;

static char CMDFILE[512];
static int CMDFILE_READY = 0;

static int HELP;
static int HELP_READY = 0;

static char IRCF[512];
static int IRCF_READY = 0;

static char IRDATA[512];
static int IRDATA_READY = 0;

static int IRBITS = 0;
static int IRBITS_READY = 0;

static int ACODE = 0;
static int ACODE_READY = 0;

static int ACON = 0;
static int ACON_READY = 0;

static int ACOFF = 0;
static int ACOFF_READY = 0;

static int ACCOLD = 0;
static int ACCOLD_READY = 0;

static int ACHOT = 0;
static int ACHOT_READY = 0;

static int ACTEMP = 0;
static int ACTEMP_READY = 0;

static input_argu_t input_var_table[] = {
	{"vid",	"", HEX, NULL, 0, "usb device version id"},
    {"uid",	"", HEX, NULL, 0, "usb device user id"},
	{"help",	"", MRK, NULL, 0, "print help message"},
	
	{"port", 	"", STR, NULL, 0, "input gpio port: a, b, c, d"},
	{"pin",	"", DEC, NULL, 0, "input gpio pin number"},
	
	{"set",    "", MRK, NULL, 0, "set io pin"},
	{"clr",    "", MRK, NULL, 0, "clear io pin"},
	{"get",    "", MRK, NULL, 0, "get io pin"},

	//"port", 	"", STR, &PORT, &PORT_READY,
	//"pin",	"", DEC, &PIN, &PIN_READY,
	
	//"wio8",	"", MRK, &WIO8, &WIO8_READY,
	//"rio8",	"", MRK, &RIO8, &RIO8_READY,
	//"cio8",	"", MRK, &CIO8, &CIO8_READY,
	//"sio8",	"", MRK, &SIO8, &SIO8_READY,
	
	//"wm8",		"", MRK, &WMEM8, &WMEM8_READY,
	//"rm8",		"", MRK, &RMEM8, &RMEM8_READY,
	//"cm8",		"", MRK, &CMEM8, &CMEM8_READY,
	//"sm8",		"", MRK, &SMEM8, &SMEM8_READY,
	
	//"sio",		"", DEC, &SETIO, &SETIO_READY,
	//"gio",		"", MRK, &GETIO, &GETIO_READY,
	//"cfgio",		"", STR, &CFGPIN, &CFGPIN_READY,
	//"isout",		"", MRK, &ISOUT, &ISOUT_READY,
	
	//"ping",	"", MRK, &ECHO, &ECHO_READY,
	//"reset",	"", MRK, &RESET, &RESET_READY,
	
	//"wrf",		"", MRK, &WRFREG, &WRFREG_READY,
	//"rrf",		"", MRK, &RRFREG, &RRFREG_READY,
	//"crf",		"", MRK, &CFR, &CFR_READY,
	//"srf",		"", MRK, &SFR, &SFR_READY,
	
	//"adr",		"", HEX, &ADR, &ADR_READY,
	//"val",		"", HEX, &VAL, &VAL_READY,
	//"bit",		"", DEC, &BIT, &BIT_READY,
	
	//"remote",	"", MRK, &REMOTE, &REMOTE_READY,
	//"file",	"", STR, &CMDFILE, &CMDFILE_READY,
	//"help",	"", MRK, &HELP, &HELP_READY,
	{"reset",  "", MRK, NULL, 0, "reset device"},
	
	{"sn",		"", STR, NULL, 0, "serial number"},
	{"id",		"", STR, NULL, 0, "set serial number"},
	{"temp",   "", MRK, NULL, 0, "read temperature sensor value"},
	{"echo",   "", MRK, NULL, 0, "RF echo command"},
	
	{"ircf",	"", STR, NULL, 0, "IR encoding arguments"},
	{"irdata",	"", STR, NULL, 0, "IR data to send, hex input"},
	{"irbits",	"", DEC, NULL, 0, "IR total bits to send"},
	
	{"ac",		"", MRK, NULL, 0, "Air-Conditioning control"},
	{"on",		"", MRK, NULL, 0, "turn on AC"},
	{"off",	"", MRK, NULL, 0, "turn off AC"},
	{"cold",	"", MRK, NULL, 0, "AC cold mode"},
	{"hot",	"", MRK, NULL, 0, "AC hot mode"},
	{"t",		"", DEC, NULL, 0, "AC temperature"},
	
	 NULL, "", UDF, NULL, 0, NULL,
};

static void processCommands(libusb_device_handle *usbdev_handle);
static int processFromFile(libusb_device_handle *usbdev_handle, const char *file);
static int clearVarTable(input_argu_t *table);
static void helpMsg(void);

int main(int argc, char **argv) {
	libusb_device_handle *usbdev_handle = NULL;
	input_argu_t *ptr;
	unsigned int usb_vid = DEFAULT_USB_DEVICE_VID;
	unsigned int usb_uid = DEFAULT_USB_DEVICE_UID;
	
	
	//if(read_input_stuff(argc, argv, input_var_table, '-')) {
	if (catchInput(argc, argv, input_var_table, '-'))
	{	
		//printf("unrecognized options\n");
		return -1;
	}	
	
	//if (HELP_READY) {
	if (isThatReady("help", input_var_table, NULL))
	{
		helpMsg();
		return 0;
	}
	
	if(libusb_init(NULL) != 0) {
		printf("init the lib-usb error\n");
		return -1;
	}
	
	// open usb device
	if (isThatReady("vid", input_var_table, &ptr))
	{
		usb_vid = *(unsigned int *)ptr->value;
	}
	if (isThatReady("uid", input_var_table, &ptr))
	{
		usb_uid = *(unsigned int *)ptr->value;
	}
	usbdev_handle = libusb_open_device_with_vid_pid(NULL, usb_vid, usb_uid);
	if(usbdev_handle == NULL) 
	{
		printf("open usb device(vid=0x%x,uid=0x%x) error\n", usb_vid, usb_uid);
		printf("are you root?\n");
	} 
	else
	{
		if (CMDFILE_READY) 
		{
			processFromFile(usbdev_handle, CMDFILE);
		} 
		else 
		{
			processCommands(usbdev_handle);
		}
		libusb_close(usbdev_handle);
	}
	libusb_exit(NULL);
	unlatchInput(input_var_table);
	return 0;
} 

int str2Hex(unsigned char c) 
{
	if ( (c >= '0') && (c <= '9') )
	{
		return (c - '0');
	}
	else if ( (c >= 'A') && (c <= 'Z') )
	{
		return (c - 'A' + 0xa);
	}
	else if ( (c >= 'a') && (c <= 'z') )
	{
		return (c - 'a' + 0xa);
	}
	else 
	{
		printf("ill: %c\n", c);
		return -1;
	}
}

int string2SerialNumber(char *str) 
{
	unsigned char sn[6] = {0};
	int i, ret;
	
	if (strcmp(str, "default") == 0)
	{
		sn[0] = 0x02;
		sn[1] = sn[2] = sn[3] = sn[4] = sn[5] = 0xe7;
	} 
	else if (strcmp(str, "random") == 0)
	{
		srand(time(0));
		for(i = 0; i < 6; i ++) 
		{
			sn[i] = rand() % 255;
		}
	}	
	else 
	{
		if (strlen(str) != 12)
		{
			return -1;
		}
		
		for(i = 0; i < 6; i ++)
		{
			ret = str2Hex(str[i * 2]);
			if (ret < 0)
			{
				return -1;
			}
			else
			{
				sn[i] = (ret << 4) & 0xf0;
			}
			
			ret = str2Hex(str[i * 2 + 1]);
			if (ret < 0)
			{
				return -1;
			}
			else
			{
				sn[i] |= (ret & 0x0f);
			}
		}
	}
	
	memcpy(str, sn, 6);
	return 0;
}

static void catchSerialNumber()
{
	input_argu_t *ptr;
	char *sn = NULL;
	int i;
	
	if (isThatReady("sn", input_var_table, &ptr) )
	{
		// printf("input sn: %s\n", ptr->value);
		if (string2SerialNumber((char *)ptr->value) != 0)
		{
			ptr->filled = 0;
		}
		else
		{
			sn = (char *)ptr->value;
			printf("--------------------------------------------------\n");
			printf("Talk to slave device S/N = ");
			for(i = 0; i < 6; i ++) 
			{
				printf("%02x", sn[i] & 0xff);
			}
			printf("\n--------------------------------------------------\n");
		}
	}
	
	if (isThatReady("id", input_var_table, &ptr) )
	{
		// printf("input sn: %s\n", ptr->value);
		if (string2SerialNumber((char *)ptr->value) != 0)
		{
			ptr->filled = 0;
		}
	}
}

static void processIDCommand(libusb_device_handle *usbdev_handle)
{
	input_argu_t *ptr;
	unsigned char *sn = NULL;
	unsigned char *id = NULL;
	int ret, startAddr = 0;
	
	if (isThatReady("id", input_var_table, &ptr) )
		id = (unsigned char *)ptr->value;
	else
		return;
	
	if (isThatReady("sn", input_var_table, &ptr) )
		sn = (unsigned char *)ptr->value;
		
	id[6] = crc7(0, id, 6);
	
	if (sn)
	{
		printf("\n******** WARNING ******** WARNING ******** WARNING ******** WARNING ********\n");
		printf("This will reset slave device S/N to {%02x%02x%02x%02x%02x%02x}, original {%02x%02x%02x%02x%02x%02x}, are you sure? (y/n)\n", id[0], id[1], id[2], id[3], id[4], id[5], sn[0], sn[1], sn[2], sn[3], sn[4], sn[5]);	
		if (getchar() == 'y')
			ret = rf_ctrl_cmd(usbdev_handle, U2WRQ_EEPROM_WRITE, 7, startAddr, id, 7, 100, FALSE, sn);
		else
			return; 
	}
	else
	{
		printf("This will reset master device S/N to {%02x%02x%02x%02x%02x%02x}, are you sure? (Y/N)\n", id[0], id[1], id[2], id[3], id[4], id[5]);	
		if (getchar() == 'y')
			ret = usb_ctrl_cmd(usbdev_handle, U2WRQ_EEPROM_WRITE, 7, startAddr, id, 7, 100, FALSE);
		else
			return;
	}
	
	if (ret != 7) 
	{
		printf("set device id error\n");
	}
	else
	{
		printf("set device id ok\n");
		printf("slave device new S/N is {%02x%02x%02x%02x%02x%02x}, will take effect after reset\n", id[0], id[1], id[2], id[3], id[4], id[5]);
	}
}

static void processIOCommand(libusb_device_handle *usbdev_handle) 
{
	int setCmd = -1, ret, index;
	input_argu_t *port;
	input_argu_t *pin;
	input_argu_t *psn;
	unsigned char avrRegAddr;
	unsigned char mask;
	unsigned char avrRegValue;
	char *sn = NULL;
	
	if (isThatReady("sn", input_var_table, &psn))
	{
		sn = (char *)psn->value;
	}
	
	if (isThatReady("set", input_var_table, NULL))
	{
		setCmd = 1;
	}
	else if(isThatReady("clr", input_var_table, NULL))
	{
		setCmd = 0;
	}
	else if (isThatReady("get", input_var_table, NULL))
	{
		setCmd = 2;
	}
	
	if(setCmd < 0)
	{
		return;
	}
	
	if ( !isThatReady("port", input_var_table, &port) ||
	     !isThatReady("pin", input_var_table, &pin) )
	{
		printf("missing \'-port\' or \'-pin\' for command \'%s\'\n", setCmd ? "-set" : "-clr");
		return;
	}
	
	if ( (strcmp(port->value, "pioa") == 0) || (strcmp(port->value, "a") == 0) )
	{
		avrRegAddr = 0x3b;
	}
	else if ( (strcmp(port->value, "piob") == 0) || (strcmp(port->value, "b") == 0) )
	{
		avrRegAddr = 0x38;
	}
	else if ( (strcmp(port->value, "pioc") == 0) || (strcmp(port->value, "c") == 0) )
	{
		avrRegAddr = 0x35;
	}
	else if ( (strcmp(port->value, "piod") == 0) || (strcmp(port->value, "d") == 0) )
	{
		avrRegAddr = 0x32;
	}
	else 
	{
		printf("unrecognized option ‘%s'\n", (char *)port->value);  
	}
	
	index = *(int *)pin->value;
	if ( (index > 7) || (index < 0) )
	{
		printf("'-pin' value must within of range 0-7, %d\n", (int)pin->value);
		return;
	}
	else
	{
		mask = (1 << index);
	}
	
	if (setCmd == 2)
	{
		// read pin value
		if (sn)
		{
			ret = rf_ctrl_cmd(usbdev_handle, U2WRQ_MEM8_RW & 0x7f, 0, avrRegAddr, &avrRegValue, 1, 500, TRUE, sn);
		}
		else 
		{
			ret = usb_ctrl_cmd(usbdev_handle, U2WRQ_MEM8_RW & 0x7f, 0, avrRegAddr, &avrRegValue, 1, 500, TRUE);
		}
		if (ret != 1)
		{
			printf("read pin error\n");
			return;
		}
		
		// printf("register: 0x%x\n", avrRegValue);
		
		if (avrRegValue & (1 << index))
		{
			printf("pin is HIGH\n");
		}
		else 
		{
			printf("pin is LOW\n");
		}
	}
	else 
	{
		// write pin value
		if (sn)
			ret = rf_ctrl_cmd(usbdev_handle, setCmd ? (U2WRQ_MEM8_BIT | 0x80) : U2WRQ_MEM8_BIT, mask, avrRegAddr, &avrRegValue, 1, 500, TRUE, sn);
		else
			ret = usb_ctrl_cmd(usbdev_handle, setCmd ? (U2WRQ_MEM8_BIT | 0x80) : U2WRQ_MEM8_BIT, mask, avrRegAddr, &avrRegValue, 1, 500, TRUE);
		
		printf("%s gpio[%s], pin %d ", setCmd ? "set" : "clear", (char *)port->value, index);
		if (ret != 1)
		{
			printf("failed!\n");
		} 
		else 
		{
			printf("ok\n");
		}
	}
}

static void processTempCommand(libusb_device_handle *usbdev_handle) 
{
	int ret = 0;
	unsigned short buffer;
	input_argu_t *ptr;
	
	if (isThatReady("temp", input_var_table, NULL))
	{
		if (isThatReady("sn", input_var_table, &ptr))
		{
			ret = rf_ctrl_cmd(usbdev_handle, U2WRQ_READ_TEMP, 2, 0, (char *)&buffer, 2, 500, TRUE, ptr->value);
		}
		else
		{
			// get temperature data
			ret = usb_ctrl_cmd(usbdev_handle, U2WRQ_READ_TEMP, 2, 0, (char *)&buffer, 2, 500, TRUE);
		}
		
		if(ret != 2)
		{
			printf("read temperature failed!\n");
			return;
		}	
		else
		{
			printf("%0.1f°C\n", (float)buffer / 16);
		}
	}	
}

static void processIRCommand(libusb_device_handle *usbdev_handle) 
{
	input_argu_t *ptr[2];
	input_argu_t *psn;
	char *sn = NULL;
	
	if (isThatReady("sn", input_var_table, &psn))
	{
		sn = (char *)psn->value;
	}
	
	// "ircf"
	if(isThatReady("ircf", input_var_table, &ptr[0]))
	{
		configIR(usbdev_handle, ptr[0]->value, sn);
	}
	
	// "irdata"
	if(isThatReady("irdata", input_var_table, &ptr[0])) 
	{
		// printf("%s\n", IRDATA);
		if(isThatReady("irbits", input_var_table, &ptr[1]))
		{
			writeIRData(usbdev_handle, (char *)ptr[0]->value, (int)ptr[1]->value, sn);
		} 
		else
		{
			writeIRData(usbdev_handle, (char *)ptr[0]->value, -1, sn);
		}
	}
}

static void processACCommand(libusb_device_handle *usbdev_handle) 
{
	input_argu_t *ptr;
	int isOn = 0, isCold = 1, temp = 26;
	
	// air conditionning control
	if(isThatReady("ac", input_var_table, NULL))
	{
		if(isThatReady("on", input_var_table, NULL))
		{
			isOn = 1;
		}
		
		if(isThatReady("off", input_var_table, NULL))
		{
			isOn = 0;
		}
			
		if(isThatReady("cold", input_var_table, NULL))
		{
			isCold = 1;
			temp = 26;
		}
		
		if(isThatReady("hot", input_var_table, NULL))
		{
			isCold = 0;
			temp = 22;
		}
		
		if(isThatReady("t", input_var_table, &ptr))
		{
			temp = *(int *)ptr->value;
		}
		
		if (isThatReady("sn", input_var_table, &ptr))
		{
			writeACCode(usbdev_handle, isOn, isCold, temp, ptr->value);
		}
		else 
		{
			writeACCode(usbdev_handle, isOn, isCold, temp, NULL);
		}
	}
}

static void processCommands(libusb_device_handle *usbdev_handle) 
{
	input_argu_t *ptr;
	int ret;
	
	catchSerialNumber();
	processACCommand(usbdev_handle);
	processIRCommand(usbdev_handle);
	processTempCommand(usbdev_handle);
	processIOCommand(usbdev_handle);
	processIDCommand(usbdev_handle);
	
	if (isThatReady("echo", input_var_table, NULL) )
	{
		if (isThatReady("sn", input_var_table, &ptr))
		{
			if (rf_ctrl_cmd(usbdev_handle, U2WRQ_IDLE, 0, 0, NULL, 0, 100, FALSE, (char *)ptr->value) == 0)
			{
				printf("device is ready\n");
			}
		}		
	}
	
	if (isThatReady("reset", input_var_table, NULL))
	{
		if (isThatReady("sn", input_var_table, &ptr))
		{
			ret = rf_ctrl_cmd(usbdev_handle, U2WRQ_MCU_RESET, 0x0709, 0x1985, NULL, 0, 100, FALSE, (char *)ptr->value);
		}
		else
		{
			ret = usb_ctrl_cmd(usbdev_handle, U2WRQ_MCU_RESET, 0x0709, 0x1985, NULL, 0, 100, FALSE);
		}
		
		if (ret == 0)
			printf("reset device ok\n");
	}
	//~ // "-wm8"
	//~ if (WMEM8_READY) {
		//~ if (ADR_READY && VAL_READY) {
			//~ if (REMOTE_READY) {
				//~ radioMem8RW(usbdev_handle, ADR & 0xFF, VAL & 0xFF, ACT_WRITE);
			//~ } else {
				//~ u2wMem8RW(usbdev_handle, ADR & 0xFF, VAL & 0xFF, ACT_WRITE);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -val for 'wm8'\n");
		//~ }			
	//~ }
	//~ 
	//~ // "-rm8"
	//~ if (RMEM8_READY) {
		//~ if (ADR_READY) {
			//~ if (REMOTE_READY) {
				//~ radioMem8RW(usbdev_handle, ADR & 0xFF, NOT_USED, ACT_READ);
			//~ } else {
				//~ u2wMem8RW(usbdev_handle, ADR & 0xFF, NOT_USED, ACT_READ);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -val for 'rm8'\n");
		//~ }			
	//~ }
	//~ 
	//~ // "-sm8"
	//~ if (SMEM8_READY) {
		//~ if (ADR_READY && BIT_READY) {
			//~ if (REMOTE_READY) {
				//~ radioMem8Bit(usbdev_handle, ADR & 0xFF, (1 << BIT) & 0xFF, ACT_SET);
			//~ } else {
				//~ u2wMem8Bit(usbdev_handle, ADR & 0xFF, (1 << BIT) & 0xFF, ACT_SET);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -bit for 'rm8'\n");
		//~ }			
	//~ }
	//~ 
	//~ // "-sm8"
	//~ if (CMEM8_READY) {
		//~ if (ADR_READY && BIT_READY) {
			//~ if (REMOTE_READY) {
				//~ radioMem8Bit(usbdev_handle, ADR & 0xFF, (1 << BIT) & 0xFF, ACT_CLEAR);
			//~ } else {
				//~ u2wMem8Bit(usbdev_handle, ADR & 0xFF, (1 << BIT) & 0xFF, ACT_CLEAR);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -bit for 'rm8'\n");
		//~ }			
	//~ }
	//~ 
	//~ // "-wio8"
	//~ if (WIO8_READY) {
		//~ if (ADR_READY && VAL_READY) {
			//~ if (REMOTE_READY) {
				//~ radioIO8RW(usbdev_handle, ADR & 0xFF, VAL & 0xFF, ACT_WRITE);
			//~ } else {
				//~ u2wIO8RW(usbdev_handle, ADR & 0xFF, VAL & 0xFF, ACT_WRITE);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -val for 'wio8'\n");
		//~ }
	//~ }
	//~ 
	//~ // "-rio8"
	//~ if (RIO8_READY) {
		//~ if (ADR_READY) {
			//~ if (REMOTE_READY) {
				//~ radioIO8RW(usbdev_handle, ADR & 0xFF, NOT_USED, ACT_READ);
			//~ } else {
				//~ u2wIO8RW(usbdev_handle, ADR & 0xFF, NOT_USED, ACT_READ);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -val for 'rio8'\n");
		//~ }
	//~ }
	//~ 
	//~ // "-cio8"
	//~ if (CIO8_READY) {
		//~ if (ADR_READY && BIT_READY) {
			//~ if (REMOTE_READY) {
				//~ radioIO8Bit(usbdev_handle, ADR, (1 << BIT) & 0xFF, ACT_CLEAR);
			//~ } else {
				//~ u2wIO8Bit(usbdev_handle, ADR, (1 << BIT) & 0xFF, ACT_READ);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -bit values for 'cio8'.''\n");
		//~ }
	//~ }
	//~ 
	//~ // "-sio8"
	//~ if (SIO8_READY) {
		//~ if (ADR_READY && BIT_READY) {
			//~ if (REMOTE_READY) {
				//~ radioIO8Bit(usbdev_handle, ADR, (1 << BIT) & 0xFF, ACT_SET);
			//~ } else {
				//~ u2wIO8Bit(usbdev_handle, ADR, (1 << BIT) & 0xFF, ACT_SET);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -bit values for 'cio8'.''\n");
		//~ }
	//~ }
	//~ 
	//~ // "-sio"	
	//~ if (SETIO_READY) {
		//~ if (PORT_READY && PIN_READY) {
			//~ if (REMOTE_READY) {
				//~ radioSetIO(usbdev_handle, PORT, PIN, SETIO ? ACT_SET : ACT_CLEAR);	
			//~ } else {
				//~ u2wSetIO(usbdev_handle, PORT, PIN, SETIO ? ACT_SET : ACT_CLEAR);
			//~ }
		//~ } else {
			//~ printf("missing -port or -pin values for 'sio'.''\n");
		//~ }
	//~ }
	//~ // "-gio"
	//~ if (GETIO_READY) {
		//~ if (PORT_READY && PIN_READY) {
			//~ if (REMOTE_READY) {
				//~ radioGetIO(usbdev_handle, PORT, PIN);
			//~ } else {
				//~ u2wGetIO(usbdev_handle, PORT, PIN);
			//~ }
		//~ } else {
			//~ printf("missing -port or -pin values for 'gio'\n");
		//~ }		
	//~ }
	//~ // "-ping"
	//~ if (ECHO_READY) {
		//~ radioPing(usbdev_handle);	
	//~ }
	//~ // "cfgio"
	//~ if (CFGPIN_READY) {
		//~ if (PORT_READY && PIN_READY) {
			//~ if (REMOTE_READY) {
				//~ radioConfigIO(usbdev_handle, PORT, PIN, CFGPIN);	
			//~ } else {
				//~ u2wConfigIO(usbdev_handle, PORT, PIN, CFGPIN);
			//~ }
		//~ } else {
			//~ printf("missing -port or -pin values for 'cfgio'\n");
		//~ }		
	//~ }
	//~ // "isout"
	//~ if (ISOUT_READY) {
		//~ if (PORT_READY && PIN_READY) {
			//~ radioCheckIO(usbdev_handle, PORT, PIN);
		//~ } else {
			//~ printf("missing -port or -pin values for 'isout'\n");
		//~ }
	//~ }
	//~ // "rfr"
	//~ if (RRFREG_READY) {
		//~ if (ADR_READY) {
			//~ if (REMOTE_READY) {
				//~ radioRFRegRW(usbdev_handle, ADR, NOT_USED, ACT_READ);
			//~ } else {
				//~ u2wRFRegRW(usbdev_handle, ADR, NOT_USED, ACT_READ);
			//~ }
		//~ } else {
			//~ printf("missing -adr for 'rfr'\n");
		//~ }
	//~ }
	//~ // "wfr"
	//~ if (WRFREG_READY) {
		//~ if (ADR_READY && VAL_READY) {
			//~ if (REMOTE_READY) {
				//~ radioRFRegRW(usbdev_handle, ADR, VAL, ACT_WRITE);
			//~ } else {
				//~ u2wRFRegRW(usbdev_handle, ADR, VAL, ACT_WRITE);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -val for 'wfr'\n");
		//~ }
	//~ }
	//~ // "cfr"
	//~ if (CFR_READY) {
		//~ if (ADR_READY && BIT_READY) {
			//~ if (REMOTE_READY) {
				//~ radioRFRegBit(usbdev_handle, ADR, BIT, ACT_CLEAR);
			//~ } else {
				//~ u2wRFRegBit(usbdev_handle, ADR, BIT, ACT_CLEAR);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -bit for 'cfr'\n");
		//~ }
	//~ }
	//~ // "sfr"
	//~ if (SFR_READY) {
		//~ if (ADR_READY && BIT_READY) {
			//~ if (REMOTE_READY) {
				//~ radioRFRegBit(usbdev_handle, ADR, BIT, ACT_SET);
			//~ } else {
				//~ u2wRFRegBit(usbdev_handle, ADR, BIT, ACT_SET);
			//~ }
		//~ } else {
			//~ printf("missing -adr or -bit for 'sfr'\n");
		//~ }
	//~ }
	//~ // "reset"
	//~ if (RESET_READY) {
		//~ if (REMOTE_READY) {
			//~ radioReset(usbdev_handle);
		//~ } else {
			//~ u2wReset(usbdev_handle);
		//~ }
	//~ }
	//~ 
}

static int processFromFile(libusb_device_handle *dev, const char *file) {
	FILE *fh;
	int count;
	char *buffer[64];
	char linebuf[2048];
	char *pch;
	int len;
	
	fh = fopen(file, "r");
	if (fh == NULL) {
		printf("open %s error\n", file);
	}
	
	while (fgets(linebuf, sizeof(linebuf), fh) != NULL) {
		count = 0;
		
		pch = strrchr(linebuf, '	'); // TAB
		if (pch)
			pch[0] = '\0';
		pch = strrchr(linebuf, '\r');
		if (pch) 
			pch[0] = '\0';
		pch = strrchr(linebuf, '\n');
		if (pch)
			pch[0] = '\0';
		
		pch = strtok (linebuf, " ,");
		while (pch != NULL) {
			if ( (pch[0] == '/') && (pch[1] == '/') ) {
				break;
			}
			// strcpy(buffer[count], pch);			
			buffer[count] = pch;
			// printf ("%s\n", buffer[count]);
			count ++;
			pch = strtok (NULL, " ,");
		}
		
		// printf("exec %s, argc=%d\n", linebuf, count);
		clearVarTable(input_var_table);
		if (read_input_stuff(count, buffer, input_var_table, '-') == 0) {
			processCommands(dev);
		} 
	}
	fclose(fh);
	return 0;
}

static int clearVarTable(input_argu_t *table) {
	int index = 0;
	
	while (table[index].fixed != NULL) {
		table[index].filled = FALSE;
		index ++;		
	}	
}

static void helpMsg() {
	int headtab = 20;
	
	printf("This is USB 2 wireless control program.	Usage:\n\n");
	printf("u2w [-options -args]\n\n");
	printf("Options:\n\n");
	
	printf("%-20s", "  -vid");
	printf("%-s", "指定打开usb设备的vid, 16进制格式。e.g. -vid 0x1234\n");
	
	printf("%-20s", "  -uid");
	printf("%-s", "指定打开usb设备的uid, 16进制格式。 e.g. -uid 0x5678\n");
	
	printf("%-20s", "  -remote");
	printf("%-s", "设置本次操作的目标是无限远程设备。\n");
	
	printf("%-20s", "  -wio8");
	printf("%-s", "写IO8寄存器，必须同时指定地址和值。 e.g. -wio8 -adr 0x2 -val 0x10\n");
	
	printf("%-20s", "  -rio8");
	printf("%-s", "读IO8寄存器，必须指定地址。 e.g. -rio8 -adr 0x1\n");
	
	printf("%-20s", "  -sio8");
	printf("%-s", "置位IO8寄存器，必须指定地址和位号。 e.g. -sio8 -adr 0x05 -bit 5\n");
	
	printf("%-20s", "  -cio8");
	printf("%-s", "清零IO8寄存器，必须指定地址和位号。 e.g. -cio8 -adr 0x02 -bit 3\n");
	
	printf("%-20s", "  -wm8,-rm8,-sm8,-cm8\n");
	printf("%-20s", " ");
	printf("%-s", "除了寄存器类型为MEM8以外，和io8命令相同。\n");	
}

#define MAX_RETRY_TIMES		100

#if (0)
int mcu_e2prom_read(libusb_device_handle *usbdev, int addr, char *buffer, int len) {
	int lenb;
	int count = 0;
	int ret;
	int retry;	
	
	while (len) {
		if( len > USB_CTRL_DATA_SIZEB ) {
			lenb = USB_CTRL_DATA_SIZEB;
		} else {
			lenb = len;
		}
		
		retry = 0;
		do {
			ret = usb_ctrl_cmd(usbdev, RQ_READ_E2PROM, lenb, addr, buffer, lenb, 500, TRUE);
			if(ret != lenb) {
				retry ++;
				printf("read eeprom retry: %d\r\n", retry);
				usleep(100000);						
			}
			// getchar();
		} while( (ret != lenb) && (retry < MAX_RETRY_TIMES) );

		if (retry >= MAX_RETRY_TIMES) {
			break;
		}		

		len -= lenb;
		count += lenb;		
		addr += lenb;
		buffer += lenb;
		//usleep(10000);
	}
	return count;
}

int mcu_e2prom_write(libusb_device_handle *usbdev, int addr, char *buffer, int len) {
	int lenb;
	int count = 0;
	int ret;
	int retry;
	
	while (len) {
		if( len > USB_CTRL_DATA_SIZEB ) {
			lenb = USB_CTRL_DATA_SIZEB;
		} else {
			lenb = len;
		}
		
		retry = 0;
		do {
			printf("mcu e2prom write %d bytes\n", lenb);
			ret = usb_ctrl_cmd(usbdev, RQ_WRITE_E2PROM, lenb, addr, buffer, lenb, 500, FALSE);
			if(ret != lenb) {
				retry ++;
				printf("write eeprom retry: %d\r\n", retry);
				// usleep(100000);						
			}
			// getchar();			
			usleep(100000);
		} while( (ret != lenb) && (retry < MAX_RETRY_TIMES) );

		if (retry >= MAX_RETRY_TIMES) {
			break;
		}		
 
		len -= lenb;
		count += lenb;
		addr += lenb;
		buffer += lenb;
		// usleep(50000);
	}
	return count;
}
#endif






